package com.xuecheng.manage_cms.service.impl;

import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.xuecheng.framework.domain.cms.CmsPage;
import com.xuecheng.framework.domain.cms.CmsTemplate;
import com.xuecheng.framework.domain.cms.response.CmsCode;
import com.xuecheng.framework.exception.ExceptionCast;
import com.xuecheng.manage_cms.dao.CmsTemplateRepository;
import com.xuecheng.manage_cms.service.CmsPageService;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Optional;

/**
 * CmsPage页面静态化处理类
 */
@Component
public class CmsPageStaticHtmlUtil {
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private CmsTemplateRepository cmsTemplateRepository;
    @Resource
    private GridFsTemplate gridFsTemplate;
    @Resource
    private GridFSBucket gridFSBucket;
    @Resource
    private CmsPageService cmsPageServiceImpl;


    /**
     * 获取数据模型
     *
     * @param pageId 页面id
     * @return 数据模型
     */
    protected Map getModelByPageId(String pageId) {

        // 取出页面信息
        CmsPage cmsPage = cmsPageServiceImpl.findById(pageId);
        if (cmsPage == null) {
            ExceptionCast.cast(CmsCode.CMS_PAGE_DOES_NOT_EXIST);
        }
        // 取出页面的DataUrl
        String dataUrl = cmsPage.getDataUrl();
        if (StringUtils.isEmpty(dataUrl)) {
            // 页面的DataUrl为空
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_DATAURLISNULL);
        }
        // 通过resultTemplate获取dataUrl数据
        ResponseEntity<Map> forEntity = restTemplate.getForEntity(dataUrl, Map.class);
        return forEntity.getBody();
    }

    /**
     * 获取页面模板信息
     *
     * @param pageId 页面id
     * @return 模板数据
     */
    protected String getTemplateByPageId(String pageId) {
        CmsPage cmsPage = cmsPageServiceImpl.findById(pageId);
        if (cmsPage == null) {
            ExceptionCast.cast(CmsCode.CMS_PAGE_DOES_NOT_EXIST);
        }
        String templateId = cmsPage.getTemplateId();
        if (StringUtils.isEmpty(templateId)) {
            ExceptionCast.cast(CmsCode.CMS_GENERATEHTML_TEMPLATEISNULL);
        }
        // 查询模板信息
        Optional<CmsTemplate> optional = cmsTemplateRepository.findById(templateId);
        if (optional.isPresent()) {
            CmsTemplate cmsTemplate = optional.get();
            // 获取模板文件id
            String templateFileId = cmsTemplate.getTemplateFileId();
            // 从GridFS中获取模板文件内容
            GridFSFile gridFSFile = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(templateFileId)));
            // 打开一个下载流
            GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
            // 创建GridFSResource对象, 获取流
            GridFsResource gridFsResource = new GridFsResource(gridFSFile, gridFSDownloadStream);
            try {
                String templateContent = IOUtils.toString(gridFsResource.getInputStream(), StandardCharsets.UTF_8);
                return templateContent;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 用模板和数据生成Html
     *
     * @param templateContent String形式的模板
     * @param model           Map类型的数据
     * @return 返回生成好的String类型的Html
     */
    protected String generateHtml(String templateContent, Map model) {
        // 创建配置对象
        Configuration configuration = new Configuration(Configuration.getVersion());
        // 创建模板加载器
        StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
        stringTemplateLoader.putTemplate("templates", templateContent);
        // 先配置对象添加模板加载器
        configuration.setTemplateLoader(stringTemplateLoader);
        // 获取模板内容
        try {
            Template template = configuration.getTemplate("templates");
            String content = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
            return content;
        } catch (IOException | TemplateException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将Html保存到GridFS中
     * @param pageId pageId
     * @param htmlContent 需要保存的Html
     * @return
     */
    protected CmsPage saveHtml(String pageId, String htmlContent){
        // 得到页面信息
        CmsPage cmsPage = cmsPageServiceImpl.findById(pageId);
        if (cmsPage==null){
            ExceptionCast.cast(CmsCode.CMS_PAGE_DOES_NOT_EXIST);
        }
        // 将htmlContent转成输入流
        InputStream inputStream = IOUtils.toInputStream(htmlContent, StandardCharsets.UTF_8);
        // 将Html文件保存到GridFS中
        // 先判断CmsPage的静态文件是不是已经存在GridFS中了
        String htmlFileId = cmsPage.getHtmlFileId();
        if (StringUtils.isNotEmpty(htmlFileId)){
            // 先删除上一次文件
            gridFsTemplate.delete(Query.query(Criteria.where("_id").is(htmlFileId)));
        }
        // 再保存
        ObjectId objectId = gridFsTemplate.store(inputStream, cmsPage.getPageName());
        // 将Html文件id更新到CmsPage中
        cmsPage.setHtmlFileId(objectId.toHexString());
        return cmsPageServiceImpl.save(cmsPage);
    }
}
